#include <stx/test/test.hpp>

TEST_CASE (core_inc)
{
    static_assert(IsAnyType<void>);
    static_assert(IsAnyType<void*>);
    static_assert(IsAnyType<int>);

    static_assert(!IsNonVoid<void>);
    static_assert(IsNonVoid<int>);

    {
        CHECK("/tmp/hello"sv == "/tmp/hello"_fp.native());
    }

    {
        gLastError().set(-1);
        CHECK(gLastError().isFailed());
        CHECK(-1 == gLastError().code);

        gLastError().clear();
        CHECK(gLastError().isGood());
        CHECK(0 == gLastError().code);

        gLastError().set(0, "msg"s);
        CHECK(gLastError().isGood());
        CHECK("msg"sv == gLastError().desc);
    }

    {
        auto v = std::vector<int>{};
        resizeDefaultInit(v, 123);
        CHECK(v.size() == 123);

        auto b = Buffer{};
        resizeDefaultInit(b, 124);
        CHECK(b.size() == 124);

        auto s = std::string{};
        resizeDefaultInit(s, 125);
        CHECK(s.size() == 125);
    }

    {
        initPosixEnv();
        auto v = ::rlimit{};
        CHECK(C_STATUS_SUCCESS == ::getrlimit(RLIMIT_NOFILE, &v));
        CHECK(v.rlim_cur == v.rlim_max);

        auto const s_max_user_watches =
            readFileToString("/proc/sys/fs/epoll/max_user_watches"_fp).get();
        auto const opt = ton(s_max_user_watches);
        CHECK(opt && *opt > 1_Mi);
    }

    {
        auto b1 = Buffer(128);
        auto b2 = b1;
        CHECK(b1.size() == b2.size());
        CHECK(b1 == b2);

        randomize(b1.data(), b2.size());
        randomize(b1.data(), b2.size());
        CHECK(b1 != b2);
        b1 = b2;
        CHECK(b1 == b2);
        b1 = std::move(b2);
        CHECK(b2.empty());
        CHECK(b1 != b2);

        auto stat = Map<std::uint8_t, std::size_t>{};
        LOOP_N (10000)
        {
            auto buf = Buffer(256);
            zero(buf);
            randomize(buf.data(), buf.size());
            ranges::for_each(buf,
                             [&](auto const n)
                             { ++stat[static_cast<std::uint8_t>(n)]; });
        }

        CHECK(ranges::all_of(stat,
                             [](auto const& item) {
                                 return item.second > 9500 &&
                                        item.second < 10500;
                             }));
    }

    setOsThreadTag("hello");
    CHECK(getOsThreadTag() == "hello"sv);
    setOsThreadTag(nullptr);
    CHECK(getOsThreadTag() == "hello"sv);

    CHECK(getOsPid() > 1);
    CHECK(getOsTid() > 1);
    CHECK(getPageSize() >= C_PAGE_SIZE);
    CHECK(!getExePathByPid(getOsPid()).empty());
    CHECK(!getExePathByPid(tos(getOsPid())).empty());
    CHECK(getExePathByPid(getOsPid()) == getExePathByPid(tos(getOsPid())));
    CHECK(getTotalNumberOfCores() > 0);
    CHECK(isMatch(
        COMPILE_DATE_TIME(),
        rgx<R"([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2})">()));

    for (auto c = '0'; c <= '9'; ++c)
    {
        CHECK(isHexChar(c));
    }

    for (auto c = 'a'; c <= 'f'; ++c)
    {
        CHECK(isHexChar(c));
    }

    for (auto c = 'A'; c <= 'F'; ++c)
    {
        CHECK(isHexChar(c));
    }

    static_assert(AllTrue<1, 1, 1>);
    static_assert(AnyTrue<0, 1, 0>);
    static_assert(NoneTrue<0, 0, 0>);
    static_assert(AllTrue<1, 1, 1, 1>);
    static_assert(!AllTrue<1, 1, 0, 1>);
    static_assert(AnyTrue<0, 1, 0, 1>);
    static_assert(!AnyTrue<0, 0, 0, 0>);
    static_assert(NoneTrue<0, 0, 0, 0>);
    static_assert(!NoneTrue<0, 1, 0, 0>);

    static_assert(-23_i8 == std::int8_t{-23});
    static_assert(23_i8 == std::int8_t{23});
    static_assert(-23_i16 == std::int16_t{-23});
    static_assert(23_i16 == std::int16_t{23});
    static_assert(-23_i32 == std::int32_t{-23});
    static_assert(23_i32 == std::int32_t{23});
    static_assert(-23_i64 == std::int64_t{-23});
    static_assert(23_i64 == std::int64_t{23});

    static_assert(23_u8 == std::uint8_t{23});
    static_assert(23_u16 == std::uint16_t{23});
    static_assert(23_u32 == std::uint32_t{23});
    static_assert(23_u64 == std::uint64_t{23});

    static_assert(1024uz == 1_Ki);
    static_assert(1024uz * 1_Ki == 1_Mi);
    static_assert(1024uz * 1_Mi == 1_Gi);
    static_assert(1024uz * 1_Gi == 1_Ti);
    static_assert(1024uz * 1_Ti == 1_Pi);
    static_assert(1024uz * 1_Pi == 1_Ei);
    static_assert(1024uz * 1_Ei == 1_Zi);
    static_assert(1024uz * 1024uz == 1_Mi);
    static_assert(1024uz * 1024uz * 1024uz == 1_Gi);
    static_assert(1024uz * 1024uz * 1024uz * 1024uz == 1_Ti);
    static_assert(1024uz * 1024uz * 1024uz * 1024uz * 1024uz == 1_Pi);
    static_assert(1024uz * 1024uz * 1024uz * 1024uz * 1024uz * 1024uz == 1_Ei);
    static_assert(
        1024uz * 1024uz * 1024uz * 1024uz * 1024uz * 1024uz * 1024uz == 1_Zi);

    static_assert(1000uz == 1_K);
    static_assert(1000uz * 1_K == 1_M);
    static_assert(1000uz * 1_M == 1_G);
    static_assert(1000uz * 1_G == 1_T);
    static_assert(1000uz * 1_T == 1_P);
    static_assert(1000uz * 1_P == 1_E);
    static_assert(1000uz * 1_E == 1_Z);
    static_assert(1000uz * 1_Z == 1_Y);

    static_assert(1000'000uz == 1_M);
    static_assert(1000'000'000uz == 1_G);
    static_assert(1000'000'000'000uz == 1_T);
    static_assert(1000'000'000'000'000uz == 1_P);
    static_assert(1000'000'000'000'000'000uz == 1_E);
    static_assert(1000'000'000'000'000'000uz * 1000uz == 1_Z);
    static_assert(1000'000'000'000'000'000uz * 1000'000uz == 1_Y);
}
